package com.freak.wanandroid.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;

import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.ColorUtils;
import androidx.multidex.MultiDexApplication;

import com.freak.wanandroid.R;
import com.freak.httpmanager.HttpMethods;
import com.freak.httpmanager.log.LogLevel;
import com.freak.httpmanager.log.LogUtil;
import com.freak.wanandroid.base.activity.BaseActivity;
import com.freak.wanandroid.base.activity.IActivityStatusBar;
import com.freak.wanandroid.model.MainActivity;
import com.freak.wanandroid.net.interceptor.AddCookiesInterceptor;
import com.freak.wanandroid.net.interceptor.SaveCookiesInterceptor;
import com.freak.wanandroid.net.util.NetStateChangeReceiver;
import com.freak.wanandroid.util.picture.CachePathUtil;
import com.freak.wanandroid.util.picture.DisplayUtil;
import com.tencent.bugly.beta.Beta;

import org.litepal.LitePal;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;


/**
 * @author Freak
 * @date 2022/9/12.
 */
public class App extends MultiDexApplication {
    public static final int DESIGN_WIDTH = 375;
    private static final int DEFAULT_TIMEOUT = 10;
    private static App sInstance;
    /**
     * 存放activity的列表
     */
    public static final HashMap<Class<?>, Activity> allActivities = new LinkedHashMap<>();
    public static BaseActivity baseActivity;

    /**
     * 缓存拍照图片路径
     */
    public File takePhotoCacheDir = null;

    public static App getInstance() {
        return sInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        sInstance = this;
        initHttpMethods();
//        registerActivityLifecycleCallbacks();
//        settingUpData();
        baseInit();
        // 注册BroadcastReceiver
        NetStateChangeReceiver.registerReceiver(this);
//        Bugly.init(getApplicationContext(), "46fb82cb75", false);
        // 数据库初始化
        LitePal.initialize(this);
        LogUtil.Builder builder = new LogUtil.Builder();
        builder.setIsPrintLog(true).setIsShowThreadInfo(true).setMethodCount(4).setTagName("WanAndroid").build();
    }

    /**
     * 注册生命周期回调
     */
    private void registerActivityLifecycleCallbacks() {
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @SuppressLint("SourceLockedOrientationActivity")
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                //限制竖屏
                //8.0.0版本系统，同时设置竖屏和设置全屏透明冲突，
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                resetDensity(getApplicationContext(), DESIGN_WIDTH);
                resetDensity(activity, DESIGN_WIDTH);
                setImmersiveStatusBar(activity);
            }

            @Override
            public void onActivityStarted(Activity activity) {
                setToolBar(activity);
                resetDensity(getApplicationContext(), DESIGN_WIDTH);
                resetDensity(activity, DESIGN_WIDTH);
            }

            @Override
            public void onActivityResumed(Activity activity) {
                resetDensity(getApplicationContext(), DESIGN_WIDTH);
                resetDensity(activity, DESIGN_WIDTH);
            }

            @Override
            public void onActivityPaused(Activity activity) {

            }

            @Override
            public void onActivityStopped(Activity activity) {

            }

            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                resetDensity(getApplicationContext(), DESIGN_WIDTH);
                resetDensity(activity, DESIGN_WIDTH);
            }

            @Override
            public void onActivityDestroyed(Activity activity) {
            }
        });
    }

    /**
     * 设置ToolBar
     *
     * @param activity Activity
     */
    void setToolBar(final Activity activity) {
        if (activity.findViewById(R.id.tool_bar) != null && ((AppCompatActivity) activity).getSupportActionBar() == null) {
            Toolbar toolbar = activity.findViewById(R.id.tool_bar);
            if (!TextUtils.isEmpty(activity.getTitle())) {
                toolbar.setTitle(activity.getTitle());
            } else {
                toolbar.setTitle("");
            }

            if (((IActivityStatusBar) activity).getStatusBarColor() != 0) {
                toolbar.setBackgroundColor(((IActivityStatusBar) activity).getStatusBarColor());
            } else {
                toolbar.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.color_white));
            }

            ((AppCompatActivity) activity).setSupportActionBar(toolbar);
            ActionBar actionBar = ((AppCompatActivity) activity).getSupportActionBar();
            if (actionBar != null) {
                actionBar.setHomeButtonEnabled(true);
                actionBar.setDisplayHomeAsUpEnabled(true);
            }
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    activity.onBackPressed();
                }
            });
        }
    }

    /**
     * 设置状态栏
     *
     * @param activity Activity
     */
    void setImmersiveStatusBar(Activity activity) {
        if (activity instanceof IActivityStatusBar) {
            if (((IActivityStatusBar) activity).getStatusBarColor() != 0) {
                setTranslucentStatus(activity);
                addImmersiveStatusBar(activity, ((IActivityStatusBar) activity).getStatusBarColor());
            } else {
                if (((IActivityStatusBar) activity).getDrawableStatusBar() != 0) {
                    setTranslucentStatus(activity);
                    addImmersiveShadeStatusBar(activity, ((IActivityStatusBar) activity).getDrawableStatusBar());
                }
            }
        }
    }

    /**
     * 添加自定义状态栏
     *
     * @param activity Activity
     * @param color    Color值
     */
    private void addImmersiveStatusBar(Activity activity, int color) {
        ViewGroup contentFrameLayout = activity.findViewById(android.R.id.content);
        View contentView = contentFrameLayout.getChildAt(0);
        if (contentView != null) {
            contentView.setFitsSystemWindows(true);
        }

        View statusBar = new View(activity);
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        if (hasNotchInScreen(activity)) {
            params.height = getNotchSize(activity)[1];
        } else {
            params.height = getStatusBarHeight();
        }
        params.height = getStatusBarHeight();
        statusBar.setLayoutParams(params);
        statusBar.setBackgroundColor(color);
        if (isLightColor(color)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                statusBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            } else {
                statusBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            }
        } else {
            statusBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
        }
        contentFrameLayout.addView(statusBar);
    }

    /**
     * 设置状态栏渐变色
     *
     * @param activity activity
     * @param drawable drawable资源文件
     */
    private void addImmersiveShadeStatusBar(Activity activity, @DrawableRes int drawable) {
        ViewGroup contentFrameLayout = activity.findViewById(android.R.id.content);
        View contentView = contentFrameLayout.getChildAt(0);
        if (contentView != null) {
            contentView.setFitsSystemWindows(true);
        }

        View statusBar = new View(activity);
        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        if (hasNotchInScreen(activity)) {
            params.height = getNotchSize(activity)[1];
        } else {
            params.height = getStatusBarHeight();
        }
//        params.height = getStatusBarHeight();
        statusBar.setLayoutParams(params);
        statusBar.setBackgroundResource(drawable);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            statusBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
        } else {
            statusBar.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
        }
        contentFrameLayout.addView(statusBar);
    }

    /**
     * 判断是否是亮色
     *
     * @param color 颜色引用值
     * @return true：是 false: 非亮色
     */
    private boolean isLightColor(@ColorInt int color) {
        return ColorUtils.calculateLuminance(color) >= 0.5;
    }

    /**
     * 获取状态栏高度
     *
     * @return 状态栏高度
     */
    private int getStatusBarHeight() {
        int statusBarHeight = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
        return statusBarHeight;
    }

    /**
     * 设置状态栏为透明 5.0以上系统状态栏透明
     *
     * @param activity Activity
     */
    private void setTranslucentStatus(Activity activity) {
        Window window = activity.getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
    }

    /**
     * 以pt为单位重新计算大小
     */
    public static void resetDensity(@NonNull Context context, float designWidth) {
        Point size = new Point();
        ((WindowManager) context.getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getSize(size);
        Resources resources = context.getResources();
        resources.getDisplayMetrics().xdpi = size.x / designWidth * 72f;
        DisplayMetrics metrics = getMetricsOnMIUI(context.getResources());
        if (metrics != null) {
            metrics.xdpi = size.x / designWidth * 72f;
        }
    }

    /**
     * 解决MIUI屏幕适配问题
     *
     * @param resources Resources
     * @return DisplayMetrics
     */
    private static DisplayMetrics getMetricsOnMIUI(Resources resources) {
        if ("MiuiResources".equals(resources.getClass().getSimpleName()) || "XResources".equals(resources.getClass().getSimpleName())) {
            try {
                Field field = Resources.class.getDeclaredField("mTmpMetrics");
                field.setAccessible(true);
                return (DisplayMetrics) field.get(resources);
            } catch (Exception e) {
                return null;
            }
        }
        return null;
    }

    /**
     * 判断是否是刘海屏  华为手机
     *
     * @param context Context
     * @return true:刘海屏 false：非刘海屏
     */
    public static boolean hasNotchInScreen(@NonNull Context context) {
        boolean ret = false;
        try {
            ClassLoader cl = context.getClassLoader();
            Class hwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = hwNotchSizeUtil.getMethod("hasNotchInScreen");
            ret = (boolean) get.invoke(hwNotchSizeUtil);
        } catch (ClassNotFoundException e) {
            LogUtil.e("hasNotchInScreen ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            LogUtil.e("hasNotchInScreen NoSuchMethodException");
        } catch (Exception e) {
            LogUtil.e("hasNotchInScreen Exception");
        }
        LogUtil.e("是否刘海屏-->" + ret);
        return ret;

    }

    /**
     * 获取刘海屏尺寸 华为手机
     *
     * @param context Context
     * @return int[]
     */
    @NonNull
    public static int[] getNotchSize(@NonNull Context context) {
        int[] ret = new int[]{0, 0};
        try {
            ClassLoader cl = context.getClassLoader();
            Class hwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = hwNotchSizeUtil.getMethod("getNotchSize");
            ret = (int[]) get.invoke(hwNotchSizeUtil);
        } catch (ClassNotFoundException e) {
            LogUtil.e("getNotchSize ClassNotFoundException");
        } catch (NoSuchMethodException e) {
            LogUtil.e("getNotchSize NoSuchMethodException");
        } catch (Exception e) {
            LogUtil.e("getNotchSize Exception");
        }
        LogUtil.e("刘海屏尺寸-->" + ret.toString());
        return ret;
    }

    /**
     * 初始化网络请求框架
     */
    private void initHttpMethods() {
        HttpMethods
                .getInstanceBuilder()
                .setBaseUrl(Constants.BASE_URL)//设置域名
                .setLogLevel(LogLevel.ERROR)//设置日志打印级别，使用默认的日志打印才需要设置这个
//                .setCookieJar(new CookieJarImpl())//设置自定义的cookiejar
//                .setLogger(new HttpLogger())//设置自定义logger，此设置是打印网络请求的数据（如果设置了自定义的，则框架默认的则不需要设置）
//                .setLevel(LoggerLevel.BODY)//设置日志打印级别（自定义logger可设置，框架默认的是BODY级别，如果上架需要关闭日志打印，则设置setIsOpenLog(false)即可）
                .setReadTimeOut(DEFAULT_TIMEOUT)
                .setConnectTimeOut(DEFAULT_TIMEOUT)
                .setWriteTimeOut(DEFAULT_TIMEOUT)
                .setInterceptor(new AddCookiesInterceptor(this))//设置拦截器
                .setInterceptor(new SaveCookiesInterceptor(this));
//                .setNetworkInterceptor(new CommonParametersInterceptor())//设置拦截器
//                .setFactory(CustomConverterFactory.create());//设置自定义解析器
//                .setInterceptors(new RefreshTokenInterceptor());//设置多个拦截器
    }

    /**
     * 腾讯bugly检测更新配置
     */
    private void settingUpData() {
        // true表示app启动自动初始化升级模块；false不好自动初始化
        // 开发者如果担心sdk初始化影响app启动速度，可以设置为false,在后面某个时刻手动调用
        Beta.autoInit = true;

        // true表示初始化时自动检查升级;
        // false表示不会自动检查升级，需要手动调用Beta.checkUpgrade()方法
        Beta.autoCheckUpgrade = true;

        // 设置升级周期为60s（默认检查周期为0s），60s内SDK不重复向后天请求策略
        Beta.initDelay = 1 * 1000;

        // 设置通知栏大图标，largeIconId为项目中的图片资源；
        Beta.largeIconId = R.mipmap.ic_launcher;

        // 设置状态栏小图标，smallIconId为项目中的图片资源id;
        Beta.smallIconId = R.mipmap.ic_launcher;

        // 设置更新弹窗默认展示的banner，defaultBannerId为项目中的图片资源Id;
        // 当后台配置的banner拉取失败时显示此banner，默认不设置则展示“loading“;
        Beta.defaultBannerId = R.mipmap.ic_launcher;

        // 设置sd卡的Download为更新资源保存目录
        // 后续更新资源会保存在此目录，需要在manifest中添加WRITE_EXTERNAL_STORAGE权限;
        Beta.storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

        // 点击过确认的弹窗在APP下次启动自动检查更新时会再次显示;
        Beta.showInterruptedStrategy = false;

        // 只允许在MainActivity上显示更新弹窗，其他activity上不显示弹窗;
        // 不设置会默认所有activity都可以显示弹窗;
        Beta.canShowUpgradeActs.add(MainActivity.class);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        // 取消BroadcastReceiver注册
        NetStateChangeReceiver.unregisterReceiver(this);
    }

    private void baseInit() {
        initTakePhotoFile();

        initDisplayOpinion();
    }

    /**
     * 初始化尺寸工具类
     */
    private void initDisplayOpinion() {
        DisplayMetrics dm = getResources().getDisplayMetrics();
        DisplayUtil.density = dm.density;
        DisplayUtil.densityDPI = dm.densityDpi;
        DisplayUtil.screenWidthPx = dm.widthPixels;
        DisplayUtil.screenhightPx = dm.heightPixels;
        DisplayUtil.screenWidthDip = DisplayUtil.px2dip(getApplicationContext(), dm.widthPixels);
        DisplayUtil.screenHightDip = DisplayUtil.px2dip(getApplicationContext(), dm.heightPixels);
    }

    /**
     * 图片存储初始化
     */
    public void initTakePhotoFile() {
        this.takePhotoCacheDir = CachePathUtil.getCachePathFile("/picture/sm_photo");
    }

    /**
     * 添加activity
     *
     * @param activity AppCompatActivity
     * @param tClass   tClass
     */
    public void addActivity(@NonNull AppCompatActivity activity, @NonNull Class<?> tClass) {
        allActivities.put(tClass, activity);
    }

    /**
     * 移除activity,代替finish
     *
     * @param activity AppCompatActivity
     */
    public void removeActivity(@NonNull AppCompatActivity activity) {
        if (allActivities.containsValue(activity)) {
            allActivities.remove(activity.getClass());
        }
    }

    /**
     * 移除所有activity并结束程序
     */
    public void finishActivity() {
        if (allActivities.size() > 0) {
            Set<Map.Entry<Class<?>, Activity>> sets = allActivities.entrySet();
            for (Map.Entry<Class<?>, Activity> s : sets) {
                if (!s.getValue().isFinishing()) {
                    s.getValue().finish();
                }
            }
            allActivities.clear();
        }
        android.os.Process.killProcess(android.os.Process.myPid());
    }


    /**
     * 移除所有的Activity
     */
    public void removeAllActivity() {
        if (allActivities.size() > 0) {
            Set<Map.Entry<Class<?>, Activity>> sets = allActivities.entrySet();
            LogUtil.d("activity堆栈  removeAllActivity  " + allActivities);
            for (Map.Entry<Class<?>, Activity> s : sets) {
                if (!s.getValue().isFinishing()) {
                    s.getValue().finish();
                }
            }
            allActivities.clear();
        }
    }

    /**
     * 判断一个Activity 是否存在
     *
     * @param clz Class
     * @return true:存在 false：不存在
     */
    public <T extends AppCompatActivity> boolean isActivityExist(@NonNull Class<T> clz) {
        boolean res;
        AppCompatActivity activity = getActivity(clz);
        if (activity == null) {
            res = false;
        } else {
            if (activity.isFinishing() || activity.isDestroyed()) {
                res = false;
            } else {
                res = true;
            }
        }
        return res;
    }

    /**
     * 获得指定activity实例
     *
     * @param clazz Activity 的类对象
     * @return AppCompatActivity
     */
    public <T extends AppCompatActivity> T getActivity(@NonNull Class<T> clazz) {
        return (T) allActivities.get(clazz);
    }
}
